package queue

import (
	C "gitee.com/ljfirst/algo-go-sdk/common/constant"
	"gitee.com/ljfirst/algo-go-sdk/src/data_structure/heap_stack_queue/stack"
)

/**
 * @author ljfirst
 * @version V1.0
 * @date 2023/6/27 01:00
 * @author-Email ljfirst@mail.ustc.edu.cn
 * @blogURL https://blog.csdn.net/ljfirst
 * @description
 * */
type StackQueue struct {
	stack1    *stack.ArrayStack // Poll 的最后一步需要进行指针交换，否则只能是for循环进行值交换
	stack2    *stack.ArrayStack
	size      int
	maxSize   int
	peekValue interface{}
}

func NewStackQueue() *StackQueue {
	return &StackQueue{
		stack1:    &stack.ArrayStack{},
		stack2:    &stack.ArrayStack{},
		size:      0,
		maxSize:   8,
		peekValue: C.ErrorNum,
	}
}

func (m *StackQueue) Offer(value interface{}) {
	if m.size == m.maxSize {
		m.Resize()
	}
	if !m.stack2.Empty() && m.stack1.Empty() {
		count := m.stack2.Size()
		for i := 0; i <= count; i++ {
			m.stack1.Push(m.stack2.Pop())
		}
	}
	if m.stack1.Size() == 0 {
		m.peekValue = value
	}
	m.stack1.Push(value)
	m.size++
}

func (m *StackQueue) Poll() interface{} {
	if m.stack1.Empty() {
		if m.stack2.Empty() {
			return C.ErrorNum
		} else {
			temp := m.stack2.Pop()
			m.peekValue = m.stack2.Peak()
			return temp
		}
	}
	count := m.stack1.Size() - 1
	for i := 0; i < count; i++ {
		m.stack2.Push(m.stack1.Pop())
	}
	temp := m.stack1.Pop()
	if !m.stack2.Empty() {
		m.peekValue = m.stack2.Peak()
	}
	m.size--
	return temp
}

func (m *StackQueue) Peak() interface{} {
	if m.stack1.Empty() && m.stack2.Empty() {
		return C.ErrorNum
	}
	return m.peekValue
}

func (m *StackQueue) Size() int {
	return m.size
}

func (m *StackQueue) Resize() {
	m.maxSize *= 2
}

func (m *StackQueue) StructName() string {
	return "StackQueue"
}
